package vsvm.graphics.charts;

import java.awt.Color;
import java.awt.Graphics2D;

import org.apache.commons.math.MathException;
import org.apache.commons.math.distribution.NormalDistributionImpl;

import vsvm.math.statistics.distributions.NormalDistribution;

public class NormalDistributionChart extends AbstractChart{
	private static final long serialVersionUID = 100L;
	
	public static final int TWO_SIDED_CRITICALAREA = 3;
	public static final int ONE_SIDED_CRITICALAREA_LEFT  = 2;
	public static final int ONE_SIDED_CRITICALAREA_RIGHT = 1;
	public static final int NO_CRITICALAREA = 0;	
	private static final int POINT_CNT = 1000;
	
	private NormalDistribution nd = null;
	private int criticalArea  = this.NO_CRITICALAREA;
	
	private boolean useEstimateValue = false;
	private double alpha = 0.05;
	private double estimateValue = 0.0;
	
	public NormalDistributionChart(String title, NormalDistribution nd) {
		super(title);
		this.nd = nd;
	}
	
	public Graphics2D drawChart(Graphics2D g) {
		return g;
	}
	
	protected void prepareColors() {
		this.setColors(new Color[]{Color.RED, Color.BLACK, new Color(200, 200, 200)});
	}
	
	protected void prepareChart() {
		double std  = nd.getStandardDeviation();
		double mean = nd.getMean();
		double start = mean - 4*std;
		double end   = mean + 4*std;
		double step  = 8*std/this.POINT_CNT;
		
		this.setXRange(start, end);
		this.setImpulses(true, 2);
		this.setImpulses(true, 0);
		this.setMarksStyle("dots", 0);
		
		for (int i = 0; i < this.POINT_CNT; i++) {
			
			if (this.criticalArea == this.TWO_SIDED_CRITICALAREA) {
				try {
					double p = nd.cumulativeProbability(start);
					if (p < alpha/2 || p > 1 - alpha/2)
						this.addPoint(2, start, nd.getDensity(start), false);
				} catch (MathException e){
					System.out.println(e.getMessage());
				}
			}
			this.addPoint(1, start, nd.getDensity(start), true);
			
			start += step;
		}		
		
		if (this.useEstimateValue)			
			this.addPoint(0, this.estimateValue, nd.getDensity(this.estimateValue), false);
		
		if (this.criticalArea != this.NO_CRITICALAREA) {
			this.addLegend(2, "Critical Area");
		}
		this.addLegend(1, "PDF");
		if (this.useEstimateValue) {
			this.addLegend(0, "Estimate");
		}
		
		this.chartPrepared = true;
	}
	
	public void setCriticalArea(int flag) {
		this.criticalArea = flag;
	}
	
	public void setEstimateValue(double value) {
		this.useEstimateValue = true;
		this.estimateValue    = value;
	}
	
	public void setUseEstimateValue(boolean use) {
		this.useEstimateValue = use;
	}

}
